package visam.core;

import java.util.Vector;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Visam {
    public static Display          display = new Display();
    public static Shell            shell   = new Shell(display);
    public static Command          command = new Command();
    public static Text             text;
    public static Vector<KeyEvent> kbseq   = new Vector<KeyEvent>();
    
    // public static Vector<Character> command = new Vector<Character>();
    
    public static void main(String[] args) {
        shell.setForeground(new Color(display, 0, 0, 0));
        try {
            if (args.length > 1) text = new Text(args[1], 10);
            shell.addKeyListener(new KeyAdapter() {
                
                @Override
                public void keyPressed(KeyEvent kevent) {
                    if (colonMode() && kevent.keyCode != 0x1b) {
                        if (kevent.keyCode == 13) {
                            command.process(text);
                            command = new Command();
                            unsetColonMode();
                        }
                        else {
                            command.handle(kevent);
                        }
                        return;
                    }
                    
                    if (kevent.keyCode == 0x1b) {
                        if (editMode()) switchToCommandMode();
                        if (colonMode()) unsetColonMode();
                        return;
                    }
                    
                    if (commandMode()) {
                        if (kevent.keyCode != 0) {
                            kbseq.add(kevent);
                            System.out.println(kevent.character);
                            
                            if (kevent.character == ':' || kevent.character == '/') {
                                setColonMode();
                                command.insert(kevent.character);
                            }
                            else if (kevent.character == 'i') {
                                switchToEditMode();
                            }
                            else
                            // if (movementcmd((char)kevent.keyCode) || kevent.character == 'u')
                            {
                                if (text.process(kbseq) == true) kbseq.clear();
                            }
                        }
                        System.out.println(kevent.toString());
                        // if (kevent.keyCode == 'r' && (kevent.stateMask & SWT.CONTROL) == SWT.CONTROL) text.redo();
                    }
                    else {
                        if (kevent.keyCode == SWT.BS)
                            text.deletePrevious();
                        else if (kevent.keyCode == SWT.DEL)
                            text.deleteNext();
                        else if ((kevent.stateMask & SWT.CONTROL) == SWT.CONTROL) {
                            if (kevent.keyCode == 'u') {
                                text.ctrl('u');
                            }
                            else if (kevent.keyCode == 'w') {
                                text.ctrl('w');
                            }
                        }
                        else if (kevent.character != 0) text.insert(kevent.character);
                    }
                    
                }
                
                @Override
                public void keyReleased(KeyEvent arg0) {
                    // TODO Auto-generated method stub
                    
                }
                
            });
            shell.addPaintListener(new PaintListener() {
                
                @Override
                public void paintControl(PaintEvent event) {
                    // TODO Auto-generated method stub
                    GC gc = event.gc;
                    gc.setFont(new Font(display, "Monaco", 11, SWT.NORMAL));
                    FontMetrics fm = gc.getFontMetrics();
                    Rectangle rect = shell.getClientArea();
                    Point p = shell.getSize();
                    Rectangle textRect = new Rectangle(rect.x, rect.y, rect.width, rect.height - 1 * fm.getHeight());
                    
                    gc.setTextAntialias(SWT.ON);
                    
                    if (text != null) text.draw(gc, textRect);
                    
                    Rectangle statusRect = new Rectangle(rect.x, rect.height - fm.getHeight(), rect.width, fm.getHeight());
                    statusRect.height = fm.getHeight();
                    if (colonMode()) {
                        command.draw(gc, statusRect);
                    }
                    else {
                        gc.drawText("\"" + (text != null ? text.getFileName() : "") + "\"" + "[" + (text != null ? text.getLine() : "0") + "," + (text != null ? text.getColumn() : "0") + "]", statusRect.x, statusRect.y);
                    }
                }
                
            });
            
            Thread t = new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        display.wake();
                        try {
                            Thread.sleep(300);
                        }
                        catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
            
            t.start();
            
            shell.open();
            
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                    shell.redraw();
                }
            }
            display.dispose();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static char[] mcmds = new char[] {
                                'w', 'W', 'e', 'E', 'b', 'B', 't', 'f', '.', '(', ')', '{', '}', '0', '$', 'h', 'j', 'k', 'l', 'H', 'M', 'L'
                                };
    
    private static boolean movementcmd(char c) {
        final int limit = mcmds.length;
        for (int i = 0; i < limit; i++) {
            if (c == mcmds[i]) return true;
        }
        return false;
    }
    
    private static boolean cmdMode = true;
    
    private static boolean commandMode() {
        return text.commandMode();
    }
    
    private static boolean editMode() {
        return text.editMode();
    }
    
    private static boolean colonMode() {
        return command.colonMode();
    }
    
    private static void switchToCommandMode() {
        text.setCommandMode();
    }
    
    private static void switchToEditMode() {
        text.setEditMode();
    }
    
    private static void setColonMode() {
        command.setColonMode();
        text.setColonMode();
    }
    
    private static void unsetColonMode() {
        command.unsetColonMode();
        text.unsetColonMode();
    }
}
